﻿using System;
//4.8.3 自定义隐式和显式转换
//隐式和显式转换也是可重载的运算符。这些转换经过重载后一般能使强关联类型（如数字类型）之间的转换变得更加简明和自然。
//如果要在弱关联类型之间进行转换，那么更适合采用以下方式：
//    编写一个具有该转换类型的参数的构造函数。
//    编写ToXXX和（静态）FromXXX方法进行类型转换。
//正如关于类型的内容所介绍的，隐式转换的原理是它们能够保证转换成功，而且转换过程不会丢失信息。相反，当运行时环境要决定转换是否会成功，或者信息在转换过程中是否会丢失时，必须使用显式转换。

//在这个例子中，我们在音符类Note和双精度浮点数类型（表示以赫兹为单位的音符频率）之间定义了转换规则：

namespace _123_运算符重载_自定义隐式和显式转换
{
    public struct Note
    {
        int value;
        public Note(int semitonesFromA) { value = semitonesFromA; }
        public static Note operator +(Note x, int semitones)
        {
            return new Note(x.value + semitones);
        }
        //implicit 隐式转换
        // 转换为赫兹
        public static implicit operator double (Note x)
        {
            return 440 * Math.Pow(2, (double)x.value / 12);
        }
        //explicit 显式转换
        // 转换自赫兹
        public static explicit operator Note(double x)
        {
            return new Note((int)(0.5 + 12 * (Math.Log(x / 440) / Math.Log(2))));
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Note n = (Note)554.37; //显式转换
            double x = n; // 隐式转换
            //提示：按照我们的方法，这个例子使用ToFrequency方法（与静态的FromFrequency方法）比隐式和显式运算符更容易实现。
            //警告：自定义转换会被as和is运算符忽略：
            Console.WriteLine(554.37 is Note); // False
            //Note n = 554.37 as Note; // 错误

            Console.ReadKey();
        }
    }
}
